
#include "MD5.h"
#include <stdio.h>
#include <string.h>

// MD5基本逻辑函数定义
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))  // F函数
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))  // G函数
#define H(x, y, z) ((x) ^ (y) ^ (z))             // H函数
#define I(x, y, z) ((y) ^ ((x) | (~z)))          // I函数
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) // 循环左移

// MD5核心变换函数
static void MD5_Transform(uint32_t state[4], const uint8_t block[64]) {
    uint32_t a = state[0], b = state[1], c = state[2], d = state[3];
    uint32_t x[16]; // 存储16个32位字
    
    // 将512位消息块转换为16个32位字(小端序)
    for (int i = 0, j = 0; j < 64; ++i, j += 4) {
        x[i] = (uint32_t)block[j] | ((uint32_t)block[j+1] << 8) | 
               ((uint32_t)block[j+2] << 16) | ((uint32_t)block[j+3] << 24);
    }

    // 第1轮变换(16次操作)
    #define FF(a, b, c, d, x, s, ac) { \
        a += F(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s); \
        a += b; \
    }
    // 完整64轮运算
    FF(a,b,c,d,x[0],7,0xd76aa478); FF(d,a,b,c,x[1],12,0xe8c7b756);
    FF(c,d,a,b,x[2],17,0x242070db); FF(b,c,d,a,x[3],22,0xc1bdceee);
    FF(a,b,c,d,x[4],7,0xf57c0faf); FF(d,a,b,c,x[5],12,0x4787c62a);
    FF(c,d,a,b,x[6],17,0xa8304613); FF(b,c,d,a,x[7],22,0xfd469501);
    FF(a,b,c,d,x[8],7,0x698098d8); FF(d,a,b,c,x[9],12,0x8b44f7af);
    FF(c,d,a,b,x[10],17,0xffff5bb1); FF(b,c,d,a,x[11],22,0x895cd7be);
    FF(a,b,c,d,x[12],7,0x6b901122); FF(d,a,b,c,x[13],12,0xfd987193);
    FF(c,d,a,b,x[14],17,0xa679438e); FF(b,c,d,a,x[15],22,0x49b40821);

      // 第2轮
    #define GG(a, b, c, d, x, s, ac) { \
        a += G(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s); \
        a += b; \
    }
    GG(a, b, c, d, x[1], 5, 0xf61e2562);
    GG(d, a, b, c, x[6], 9, 0xc040b340);
    GG(c, d, a, b, x[11], 14, 0x265e5a51);
    GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
    GG(a, b, c, d, x[5], 5, 0xd62f105d);
    GG(d, a, b, c, x[10], 9, 0x02441453);
    GG(c, d, a, b, x[15], 14, 0xd8a1e681);
    GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
    GG(a, b, c, d, x[9], 5, 0x21e1cde6);
    GG(d, a, b, c, x[14], 9, 0xc33707d6);
    GG(c, d, a, b, x[3], 14, 0xf4d50d87);
    GG(b, c, d, a, x[8], 20, 0x455a14ed);
    GG(a, b, c, d, x[13], 5, 0xa9e3e905);
    GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
    GG(c, d, a, b, x[7], 14, 0x676f02d9);
    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);

    // 第3轮
    #define HH(a, b, c, d, x, s, ac) { \
        a += H(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s); \
        a += b; \
    }
    HH(a, b, c, d, x[5], 4, 0xfffa3942);
    HH(d, a, b, c, x[8], 11, 0x8771f681);
    HH(c, d, a, b, x[11], 16, 0x6d9d6122);
    HH(b, c, d, a, x[14], 23, 0xfde5380c);
    HH(a, b, c, d, x[1], 4, 0xa4beea44);
    HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
    HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
    HH(b, c, d, a, x[10], 23, 0xbebfbc70);
    HH(a, b, c, d, x[13], 4, 0x289b7ec6);
    HH(d, a, b, c, x[0], 11, 0xeaa127fa);
    HH(c, d, a, b, x[3], 16, 0xd4ef3085);
    HH(b, c, d, a, x[6], 23, 0x04881d05);
    HH(a, b, c, d, x[9], 4, 0xd9d4d039);
    HH(d, a, b, c, x[12], 11, 0xe6db99e5);
    HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
    HH(b, c, d, a, x[2], 23, 0xc4ac5665);

    // 第4轮
    #define II(a, b, c, d, x, s, ac) { \
        a += I(b, c, d) + x + ac; \
        a = ROTATE_LEFT(a, s); \
        a += b; \
    }
    II(a, b, c, d, x[0], 6, 0xf4292244);
    II(d, a, b, c, x[7], 10, 0x432aff97);
    II(c, d, a, b, x[14], 15, 0xab9423a7);
    II(b, c, d, a, x[5], 21, 0xfc93a039);
    II(a, b, c, d, x[12], 6, 0x655b59c3);
    II(d, a, b, c, x[3], 10, 0x8f0ccc92);
    II(c, d, a, b, x[10], 15, 0xffeff47d);
    II(b, c, d, a, x[1], 21, 0x85845dd1);
    II(a, b, c, d, x[8], 6, 0x6fa87e4f);
    II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
    II(c, d, a, b, x[6], 15, 0xa3014314);
    II(b, c, d, a, x[13], 21, 0x4e0811a1);
    II(a, b, c, d, x[4], 6, 0xf7537e82);
    II(d, a, b, c, x[11], 10, 0xbd3af235);
    II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
    II(b, c, d, a, x[9], 21, 0xeb86d391);

    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;

    // 清除敏感数据
    memset(x, 0, sizeof(x));
}

// 初始化MD5上下文
void MD5_Init(MD5_CTX *context) {
    context->count[0] = context->count[1] = 0; // 重置计数器
    
    // 初始化状态变量(魔数)
    context->state[0] = 0x67452301;
    context->state[1] = 0xefcdab89;
    context->state[2] = 0x98badcfe;
    context->state[3] = 0x10325476;
}

// 更新MD5计算过程
void MD5_Update(MD5_CTX *context, const uint8_t *input, size_t input_len) {
    uint32_t i, index, part_len;
    
    // 计算当前buffer中的字节数
    index = (uint32_t)((context->count[0] >> 3) & 0x3F);
    
    // 更新消息长度计数器(64位)
    if ((context->count[0] += ((uint32_t)input_len << 3)) < ((uint32_t)input_len << 3))
        context->count[1]++;
    context->count[1] += ((uint32_t)input_len >> 29);
    
    // 处理输入数据
    part_len = 64 - index;
    if (input_len >= part_len) {
        memcpy(&context->buffer[index], input, part_len);
        MD5_Transform(context->state, context->buffer);
        
        // 处理完整的512位块
        for (i = part_len; i + 63 < input_len; i += 64)
            MD5_Transform(context->state, &input[i]);
        
        index = 0;
    } else {
        i = 0;
    }
    
    // 缓存剩余数据
    memcpy(&context->buffer[index], &input[i], input_len - i);
}

// 结束MD5计算并输出结果
void MD5_Final(uint8_t digest[16], MD5_CTX *context) {
    uint8_t bits[8];
    uint32_t index, pad_len;
    
    // 保存消息长度(64位)
    for (int i = 0; i < 8; i++)
        bits[i] = (uint8_t)((context->count[i>>2] >> ((i&3) << 3)) & 0xFF);
    
    // 填充1和0直到448位(mod 512)
    index = (uint32_t)((context->count[0] >> 3) & 0x3f);
    pad_len = (index < 56) ? (56 - index) : (120 - index);
    MD5_Update(context, (uint8_t*)"\x80", 1); // 填充1个1
    while (pad_len-- > 1) MD5_Update(context, (uint8_t*)"\0", 1); // 填充0
    
    // 附加原始消息长度
    MD5_Update(context, bits, 8);
    
    // 输出128位哈希值
    for (int i = 0; i < 4; i++) {
        digest[i]      = (uint8_t)((context->state[0] >> (i*8)) & 0xFF);
        digest[i+4]    = (uint8_t)((context->state[1] >> (i*8)) & 0xFF);
        digest[i+8]    = (uint8_t)((context->state[2] >> (i*8)) & 0xFF);
        digest[i+12]   = (uint8_t)((context->state[3] >> (i*8)) & 0xFF);
    }
    
    // 清除敏感数据
    memset(context, 0, sizeof(*context));
}

// 计算文件的MD5值
int MD5_File(const char *filename, uint8_t digest[16]) {
    FILE *file = fopen(filename, "rb");
    if (!file) return -1; // 文件打开失败

    MD5_CTX context;
    MD5_Init(&context);

    // 分块读取文件内容(4KB缓冲区)
    uint8_t buffer[4096];
    size_t bytesRead;
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) != 0) {
        MD5_Update(&context, buffer, bytesRead);
    }

    MD5_Final(digest, &context);
    fclose(file);
    return 0; // 成功
}

// 将MD5值转换为可读字符串
void MD5_ToString(const uint8_t digest[16], char output[33]) {
    static const char hex[] = "0123456789abcdef"; // 十六进制字符表
    for (int i = 0; i < 16; i++) {
        output[i*2]   = hex[(digest[i] >> 4) & 0xF]; // 高4位
        output[i*2+1] = hex[digest[i] & 0xF];        // 低4位
    }
    output[32] = '\0'; // 字符串结束符
}
